package main

import (
	"fmt"
	"math"
	"time"
)

// 储能系统结构体
type EnergyStorage struct {
	Capacity      float64 // 总容量 (kWh)
	CurrentEnergy float64 // 当前储能 (kWh)
	MaxChargeRate float64 // 最大充电功率 (kW)
	MaxDischargeRate float64 // 最大放电功率 (kW)
	Efficiency    float64 // 充放电效率
}

// 需量控制器
type DemandController struct {
	Forecaster    *LoadForecaster
	Storage       *EnergyStorage
	MaxDemand     float64   // 合同需量限制 (kW)
	DemandWindow  time.Time // 需量计算窗口开始时间
	CurrentDemand float64   // 当前需量 (kW)
	History       []float64 // 历史负荷数据
}

// 初始化需量控制器
func NewDemandController(forecaster *LoadForecaster, storage *EnergyStorage, maxDemand float64) *DemandController {
	return &DemandController{
		Forecaster:   forecaster,
		Storage:      storage,
		MaxDemand:    maxDemand,
		DemandWindow: time.Now(),
	}
}

// 动态需量计算算法
func (dc *DemandController) CalculateDynamicDemand(currentLoad float64) (float64, float64) {
	// 1. 更新历史数据
	dc.History = append(dc.History, currentLoad)
	if len(dc.History) > 1440 { // 保留最近24小时数据(每分钟一个点)
		dc.History = dc.History[1:]
	}

	// 2. 预测未来15分钟负荷
	prediction := dc.Forecaster.Predict(15) // 预测15个点(假设每分钟一个点)

	// 3. 计算当前需量(滑动窗口最大值)
	windowSize := 15 // 15分钟需量窗口
	currentDemand := maxInWindow(dc.History, windowSize)

	// 4. 储能调度决策
	storageAction := 0.0
	if currentDemand > dc.MaxDemand {
		// 计算需量超出部分
		excess := currentDemand - dc.MaxDemand
		
		// 检查储能能否吸收超出部分
		availableDischarge := math.Min(dc.Storage.CurrentEnergy, dc.Storage.MaxDischargeRate)
		storageAction = math.Min(excess, availableDischarge)
		
		// 更新储能状态
		dc.Storage.CurrentEnergy -= storageAction / dc.Storage.Efficiency
	}

	// 5. 更新当前需量
	dc.CurrentDemand = currentDemand - storageAction

	return dc.CurrentDemand, storageAction
}

// 辅助函数：计算滑动窗口最大值
func maxInWindow(data []float64, window int) float64 {
	if len(data) < window {
		return max(data...)
	}
	
	maxVal := 0.0
	for i := 0; i <= len(data)-window; i++ {
		windowMax := max(data[i:i+window]...)
		if windowMax > maxVal {
			maxVal = windowMax
		}
	}
	return maxVal
}

// 辅助函数：求最大值
func max(values ...float64) float64 {
	m := values[0]
	for _, v := range values[1:] {
		if v > m {
			m = v
		}
	}
	return m
}